package com.framework.common.util.system;

import com.framework.common.util.other.SymbolUtil;
import javax.imageio.ImageIO;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * @author 龘鵺
 * @version 1.0
 * @className com.framework.common.util.system
 * @description 验证码生成图片工具类
 * @datetime 2019-01-09 11:11:11
 */
public class CaptchaUtil {
    /**
     * 验证码超时时间
     */
    public static final Integer CAPTCHA_EXPIRED_TIME = 60;
    /**
     * 验证码在session中的key
     */
    public static final String CAPTCHA_SESSION_KEY = "CAPTCHA_SESSION_KEY";
    /**
     * 验证码在session中的key
     */
    public static final String CAPTCHA_CODE = "captchaCode";
    /**
     * 图形验证码字符串
     */
    private static char[] strs = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789".toCharArray();
    /**
     * 计算验数字字符串
     */
    private static char[] numbers = "0123456789".toCharArray();
    /**
     * 计算符号字符串
     */
    private static char[] symbol = "+-x".toCharArray();
    /**
     * 宽度
     */
    private static int width = 90;
    /**
     * 高度
     */
    private static int height = 34;


    /**
     * @param s 1 最小颜色数字
     * @param e 2 最大颜色数字
     * @return java.awt.Color
     * @title 获取随机颜色
     * @description 获取随机颜色
     * @author 龘鵺
     * @datetime 2024-07-02 16:25:18
     */
    public static Color getRandColor(int s, int e) {
        Random random = new Random();
        if (s > 255) {
            s = 255;
        }
        if (e > 255) {
            e = 255;
        }
        int r = s + random.nextInt(e - s);
        int g = s + random.nextInt(e - s);
        int b = s + random.nextInt(e - s);
        return new Color(r, g, b);
    }

    /**
     * @param request  1 请求对象
     * @param response 2 响应对象
     * @title 计算图形验证码
     * @description 计算图形验证码
     * @author 龘鵺
     * @datetime 2024-07-02 17:19:34
     */
    public static void computeCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 在内存中创建图象
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);

        // 获取图形上下文
        Graphics g = image.getGraphics();

        // 生成随机类
        Random random = new Random();

        // 设定背景色
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);

        // 设定字体
        g.setFont(new Font("Times New Roman", Font.PLAIN, 18));

        // 画边框
        // g.setColor(new Color());
        // g.drawRect(0,0,width-1,height-1);

        // 竖线 = 图片背景随机产生255条干扰线，使图象中的认证码不易被其它程序探测到
        g.setColor(getRandColor(160, 200));
        for (int i = 0; i < 100; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }
//        int xl = random.nextInt(12);
//        int yl = random.nextInt(12);
//        g.drawLine(width, height, 255, 255);
//        // 取随机产生的认证码(4位数字)
//        /**第一位数字*/
//        StringBuffer sb = new StringBuffer();
//        int index, len = numbers.length;
//        index = random.nextInt(len);
//        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
//                random.nextInt(255)));
//        g.setFont(new Font("Arial", Font.ITALIC, 16));// 输出的字体和大小
//        g.drawString("" + numbers[index], (0 * 10), 26);// 写什么数字，在图片的什么位置画
//        sb.append(numbers[index]);
//        /**第一位符号*/
//        int index1, len1 = symbol.length;
//        index1 = random.nextInt(len1);
//        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
//                random.nextInt(255)));
//        g.setFont(new Font("Arial", Font.ITALIC, 16));// 输出的字体和大小
//        g.drawString("" + symbol[index1], (1 * 10), 26);// 写什么数字，在图片的什么位置画
//        sb.append(symbol[index1]);
//
//        /**第二位数字*/
//        int index2, len2 = numbers.length;
//        index2 = random.nextInt(len2);
//        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
//                random.nextInt(255)));
//        g.setFont(new Font("Arial", Font.ITALIC, 16));// 输出的字体和大小
//        /**第二位符号*/
//        if (String.valueOf(symbol[index1]).equals("-")) {
//            if (Integer.parseInt(String.valueOf(numbers[index])) < Integer.parseInt(String.valueOf(numbers[index2]))) {
//                index2 = index;
//            }
//        }
//        g.drawString("" + numbers[index2], (2 * 10), 26);// 写什么数字，在图片的什么位置画
//        sb.append(numbers[index2]);
//
//        /**第三位符号*/
//        int index3, len3 = symbol.length;
//        index3 = random.nextInt(len3);
//        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
//                random.nextInt(255)));
//        g.setFont(new Font("Arial", Font.ITALIC, 16));// 输出的字体和大小
//        g.drawString("" + symbol[index3], (3 * 10), 26);// 写什么数字，在图片的什么位置画
//        sb.append(symbol[index3]);
//
//        /**第三位数字*/
//        g.drawString("" + numbers[index3], (4 * 10), 26);// 写什么数字，在图片的什么位置画
//        sb.append(numbers[index3]);
//        /**第四位符号*/
//        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
//                random.nextInt(255)));
//        g.setFont(new Font("Arial", Font.ITALIC, 16));// 输出的字体和大小
//        g.drawString("=", (5 * 10), 26);// 写什么数字，在图片的什么位置画
//        sb.append("=");
//        /**第五位符号*/
//        g.setColor(new Color(random.nextInt(88), random.nextInt(188),
//                random.nextInt(255)));
//        g.setFont(new Font("Arial", Font.ITALIC, 16));// 输出的字体和大小
//        g.drawString("?", (6 * 10), 26);// 写什么数字，在图片的什么位置画
//        sb.append("?");

        String[] str = new String[]{
                numbers[random.nextInt(numbers.length)] + "",
                symbol[random.nextInt(symbol.length)] + "",
                numbers[random.nextInt(numbers.length)] + "",
                symbol[random.nextInt(symbol.length)] + "",
                numbers[random.nextInt(numbers.length)] + "",
                SymbolUtil.NO_INPUT_METHOD_EQUAL_SIGN, SymbolUtil.NO_INPUT_QUESTION_MARK_PLUS
        };
        StringBuilder sb = new StringBuilder();
        StringBuilder ab = new StringBuilder();
        for (int i = 0; i < 7; i++) {
            int x = random.nextInt(10);
            int y = random.nextInt(10);
            if (x < 5) {
                x = 5;
            }
            g.setColor(new Color(random.nextInt(88), random.nextInt(188),
                    random.nextInt(255)));
            g.setFont(new Font("Arial", Font.ITALIC, 16));// 输出的字体和大小
            g.drawString("" + str[i], (i * 10 + x), 20 + y);// 写什么数字，在图片的什么位置画
            sb.append(str[i]);
            if (i < 5) {
                if (str[i].equals("x")) {
                    ab.append("*");
                    continue;
                }
                ab.append(str[i]);
            }
        }
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        Object value = engine.eval(ab.toString());
//        System.out.println(ab.toString());
//        System.out.println(value);
        // 横线 = 文字上面随机产生40条干扰线，使图象中的认证码不易被其它程序探测到
        g.setColor(getRandColor(180, 255));
        for (int i = 0; i < 40; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }
        // 存放session缓存
        request.getSession().setAttribute(CAPTCHA_SESSION_KEY, String.valueOf(value));
        // 图象生效
        g.dispose();
        ServletOutputStream out = response.getOutputStream();
        // 输出图象到页面
        ImageIO.write(image, "JPEG", out);
        // 以下关闭输入流！
        try {
            out.flush();
        } finally {
            out.close();
        }
    }

    /**
     * @param request  1 请求对象
     * @param response 2 响应对象
     * @title 图形验证码生成
     * @description 图形验证码生成
     * @author 龘鵺
     * @datetime 2024-07-02 17:38:45
     */
    public static void validateCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 在内存中创建图象
        BufferedImage img = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        // 得到该图片的绘图对象
        Graphics g = img.getGraphics();
        // 生成随机类
        Random random = new Random();

        // 随机产生155条干扰线，使图象中的认证码不易被其它程序探测到
        // 填充整个图片的颜色
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);

        // 设定字体
        g.setFont(new Font("Times New Roman", Font.PLAIN, 18));

        // 画边框
        // g.setColor(new Color());
        // g.drawRect(0,0,width-1,height-1);

        // 背景图层随机产生255条干扰线，使图象中的认证码不易被其它程序探测到
        g.setColor(getRandColor(160, 200));
        for (int i = 0; i < 255; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }

        Random r = new Random();
        Color c = new Color(200, 150, 255);
        g.setColor(c);

        // 向图片中输出数字和字母
        StringBuffer value = new StringBuffer();
        int index, len = strs.length;
        for (int i = 0; i < 4; i++) {
            int x = random.nextInt(10);
            int y = random.nextInt(10);
            if (x < 5) {
                x = 5;
            }
            index = r.nextInt(len);
            g.setColor(new Color(r.nextInt(88), r.nextInt(188), r
                    .nextInt(255)));
            g.setFont(new Font("Arial", Font.BOLD | Font.ITALIC, 18));// 输出的字体和大小
            g.drawString("" + strs[index], (i * 20 + x), 20 + y);// 写什么数字，在图片的什么位置画
            value.append(strs[index]);
        }

        // 背景图层随机产生255条干扰线，使图象中的认证码不易被其它程序探测到
        g.setColor(getRandColor(160, 255));
        for (int i = 0; i < 40; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }

        // 存放session缓存
        request.getSession().setAttribute(CAPTCHA_SESSION_KEY, String.valueOf(value));

        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(img, "JPG", out);
        try {
            out.flush();
        } finally {
            out.close();
        }
    }

}
